#include <sys/select.h>
#include <unistd.h>
#include <stdlib.h>
#include "Log.hpp"
#include "EventLoop.hpp"

#define MAX 1024

using namespace ns_log;

class SelectDispachter : public Dispatcher
{
public:
    // 初始化 select poll epoll 三者之一需要的数据块
    SelectDispachter(EventLoop *evLoop);
    ~SelectDispachter();
    // 添加节点
    int add();
    // 删除节点
    int remove();
    // 修改节点
    int modify();
    // 事件检测
    int dispatch(int timeout /* 单位：s*/);

private:
    void SetFdSet();
    void ClearFdSet();

private:
    int maxfd = -1;
    fd_set rfds;
    fd_set wfds;
};

SelectDispachter::SelectDispachter(EventLoop *evLoop)
    : Dispatcher(evLoop)
{
    FD_ZERO(&rfds);
    FD_ZERO(&wfds);
}
void SelectDispachter::SetFdSet()
{
    int fd = _channel->_fd;
    if (_channel->_events & ReadEvent)
        FD_SET(fd, &rfds);
    if (_channel->_events & WriteEvent)
        FD_SET(fd, &wfds);
    if (fd > maxfd)
        maxfd = fd;
}
void SelectDispachter::ClearFdSet()
{
    int fd = _channel->_fd;
    if (_channel->_events & ReadEvent)
        FD_CLR(fd, &rfds);
    if (_channel->_events & WriteEvent)
        FD_CLR(fd, &wfds);
    close(fd);
}
int SelectDispachter::add()
{
    SetFdSet();
    return 0;
}
int SelectDispachter::remove()
{
    ClearFdSet();
    return 0;
}
int SelectDispachter::modify()
{
    SetFdSet();
    ClearFdSet();
    return 0;
}
int SelectDispachter::dispatch(int timeout)
{
    fd_set rfdsTemp = rfds;
    fd_set wfdsTemp = wfds;
    timeval t;
    t.tv_sec = timeout;
    t.tv_usec = 0;
    select(maxfd + 1, &rfdsTemp, &wfdsTemp, nullptr, &t);
    for (int i = 0; i <= maxfd; ++i)
    {
        if (FD_ISSET(i, &rfdsTemp))
        {
            _evLoop->activate(i, ReadEvent);
        }
        if (FD_ISSET(i, &wfdsTemp))
        {
            _evLoop->activate(i, WriteEvent);
        }
    }
    return 0;
}
SelectDispachter::~SelectDispachter()
{
}